#ifndef __M_SERVER_H__
#define __M_SERVER_H__
#include <iostream>
#include <vector>
#include <string>
#include <cassert>
#include <cstring>
#include <ctime>
#include <functional>
#include <unordered_map>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <memory>
#include <typeinfo>
#include <fcntl.h>
#include <signal.h>
#include <unistd.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <sys/epoll.h>
#include <sys/eventfd.h>
#include <sys/timerfd.h>
#include <thread>
#include <sys/eventfd.h>

#define INF 0
#define DBG 1
#define ERR 2
#define LOG_LEVEL DBG

#define LOG(level, format, ...)                                                                                        \
    do                                                                                                                 \
    {                                                                                                                  \
        if (level < LOG_LEVEL)                                                                                         \
            break;                                                                                                     \
        time_t t = time(NULL);                                                                                         \
        struct tm *ltm = localtime(&t);                                                                                \
        char tmp[32] = {0};                                                                                            \
        strftime(tmp, 31, "%H:%M:%S", ltm);                                                                            \
        fprintf(stdout, "[%p %s %s:%d] " format "\n", (void *)pthread_self(), tmp, __FILE__, __LINE__, ##__VA_ARGS__); \
    } while (0)

#define INF_LOG(format, ...) LOG(INF, format, ##__VA_ARGS__)
#define DBG_LOG(format, ...) LOG(DBG, format, ##__VA_ARGS__)
#define ERR_LOG(format, ...) LOG(ERR, format, ##__VA_ARGS__)

// 缓冲区设计
#define BUFFER_SIZE 1024
#define MAX_CAPACITY 1048576

class Buffer
{
private:
    std::vector<char> _buffer; // 缓冲区
    size_t _write_pos;         // 写偏移
    size_t _read_pos;          // 读偏移
    size_t _capacity;          // 总容量

public:
    // 构造函数
    Buffer() : _buffer(BUFFER_SIZE, 0), _write_pos(0), _read_pos(0), _capacity(BUFFER_SIZE) {}
    Buffer(const Buffer &Buf) : _buffer(Buf._buffer), _write_pos(Buf._write_pos), _read_pos(Buf._read_pos), _capacity(Buf._capacity) {}
    // 赋值运算符重载
    Buffer &operator=(Buffer Buf)
    {
        std::swap(_buffer, Buf._buffer);
        std::swap(_write_pos, Buf._write_pos);
        std::swap(_read_pos, Buf._read_pos);
        std::swap(_capacity, Buf._capacity);
        return *this;
    }

public:
    // 单项功能设计

    // 调整缓冲区大小
    void Resize(uint32_t size)
    {
        _buffer.resize(size);
        _capacity = size;
        if (_write_pos > _capacity)
            _write_pos = _capacity;
    }

    // 获取缓冲区首部地址
    char *Begin()
    {
        return &_buffer[0];
    }

    // 获取读地址
    char *ReadAddress()
    {
        return &_buffer[_read_pos];
    }

    // 获取写地址
    char *WriteAddress()
    {
        return &_buffer[_write_pos];
    }

    // 获取当前缓冲区中的数据长度
    size_t DataLength()
    {
        return _write_pos - _read_pos;
    }

    // 更新读偏移
    void ModifyReadOffset(size_t len)
    {
        _read_pos += len;
    }

    // 更新写偏移
    void ModifyWriteOffset(size_t len)
    {
        _write_pos += len;
    }

    // 获取头部剩余空间
    size_t HeadRemainSpace()
    {
        return _read_pos;
    }

    // 获取尾部剩余空间
    size_t TailRemainSpace()
    {
        return _capacity - _write_pos;
    }

    // 判断尾部剩余空间是否足够写入定长数据：足够写入则直接返回
    // 不够写入则再做判断：1、头部剩余空间+尾部剩余空间是够足够写入，足够则移动数据 2、不够则直接扩容
    void ModifyRemainSpace(size_t len)
    {
        if (TailRemainSpace() >= len)
            return;
        if (HeadRemainSpace() + TailRemainSpace() >= len)
        {
            int datasize = DataLength();
            std::copy(ReadAddress(), WriteAddress(), Begin());
            _read_pos = 0;
            _write_pos = datasize;
        }
        else
        {
            // 扩容
            int new_capacity = _capacity + len;
            assert(new_capacity < MAX_CAPACITY);
            _buffer.resize(new_capacity);
            _capacity = new_capacity;
        }
    }

    // 向缓冲区写入定长数据
    // 1、以指针的形式
    void WriteAsStr(const char *sptr, size_t len)
    {
        if (len == 0)
            return;
        ModifyRemainSpace(len); // 先做判断
        std::copy(sptr, sptr + len, WriteAddress());
    }
    void WriteAsStrAndPush(const char *sptr, size_t len)
    {
        WriteAsStr(sptr, len);
        ModifyWriteOffset(len);
    }

    // 2、以string的形式
    void WriteAsString(const std::string &str)
    {
        WriteAsStr(str.c_str(), str.size());
    }
    void WriteAsStringAndPush(const std::string &str)
    {
        WriteAsString(str);
        ModifyWriteOffset(str.size());
    }

    // 3、以Buffer的形式
    void WriteAsBuffer(Buffer &buffer)
    {
        WriteAsStr(buffer.ReadAddress(), buffer.DataLength());
    }
    void WriteAsBufferAndPush(Buffer &buffer)
    {
        WriteAsBuffer(buffer);
        ModifyWriteOffset(buffer.DataLength());
    }

    // 从缓冲区中读取定长数据
    // 1、以指针的形式
    size_t ReadAsStr(char *sptr, size_t len)
    {
        int available_data = DataLength();
        if (available_data < len)
            len = available_data; // 先做判断
        std::copy(ReadAddress(), ReadAddress() + len, sptr);
        return len;
    }
    size_t ReadAsStrAndPop(char *sptr, size_t len)
    {
        int ret = ReadAsStr(sptr, len);
        ModifyReadOffset(ret);
        return ret;
    }

    // 2、以string的形式
    size_t ReadAsString(std::string &str, size_t len)
    {
        int available_data = DataLength();
        // 如果期望读取的数据大于当前数据总数，直接返回当前缓冲区中的所有数据
        if (available_data < len)
            len = available_data; // 先做判断
        str.resize(len);
        return ReadAsStr(&str[0], len);
    }
    size_t ReadAsStringAndPop(std::string &str, size_t len)
    {
        int ret = ReadAsString(str, len);
        ModifyReadOffset(ret);
        return ret;
    }

    // 3、以Buffer的形式
    size_t ReadAsBuffer(Buffer &buffer, size_t len)
    {
        if (buffer._capacity < len)
            buffer.Resize(len);
        int ret = ReadAsStr(buffer.ReadAddress(), len);
        buffer.ModifyWriteOffset(ret); // write指针要随着写入数据的增多而移动
        return ret;
    }
    size_t ReadAsBufferAndPop(Buffer &buffer, size_t len)
    {
        int ret = ReadAsBuffer(buffer, len);
        ModifyReadOffset(ret);
        return ret;
    }

    /*memchr 函数的主要作用是在一个指定长度的内存区域中查找一个特定的字节值。 void *memchr(const void *s, int c, size_t n);*/
    char *FindLineEnd()
    {
        char *ret = (char *)memchr(ReadAddress(), '\n', DataLength());
        return ret;
    }

    // 按行读取缓冲区中的内容
    std::string GetLine()
    {
        std::string temp;
        char *ret = nullptr;
        if ((ret = FindLineEnd()) == nullptr)
            return temp;
        ReadAsString(temp, ret - ReadAddress() + 1);
        return temp;
    }
    std::string GetLineAndPop()
    {
        std::string temp = GetLine();
        if (!temp.empty())
        {
            ModifyReadOffset(temp.size());
        }
        return temp;
    }

    // 清空缓冲区
    void Clear()
    {
        // 将偏移量归0即可，后续覆盖写入
        _write_pos = 0;
        _read_pos = 0;
    }
    void Print()
    {
        char *begin = ReadAddress();
        while (begin != WriteAddress())
        {
            printf("%c", *begin);
            begin++;
        }
        printf("\n");
    }
};
// 勘误记录
// date 2025.1.10
// 在Buffer a;与Buffer b;之间的读取与写入中，例如要从a中读取len个数据放入b中时，在函数设计时要注意b的write指针要随着写入数据的增多而移动

#define MAX_LISTEN 1024
class Socket
{
private:
    int _sockfd;

public:
    using ptr = std::shared_ptr<Socket>;
    Socket() : _sockfd(-1) {}
    Socket(int fd) : _sockfd(fd) {}
    ~Socket()
    {
        Close();
    }
    int Fd() { return _sockfd; }
    // 创建套接字
    bool Create()
    {
        // int socket(int domain, int type, int protocol)
        _sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
        if (_sockfd < 0)
        {
            ERR_LOG("CREATE SOCKET FAILED!!");
            return false;
        }
        return true;
    }
    // 绑定地址信息
    bool Bind(const std::string &ip, uint16_t port)
    {
        struct sockaddr_in addr;
        addr.sin_family = AF_INET;
        addr.sin_port = htons(port);
        addr.sin_addr.s_addr = inet_addr(ip.c_str());
        socklen_t len = sizeof(struct sockaddr_in);
        // int bind(int sockfd, struct sockaddr*addr, socklen_t len);
        int ret = bind(_sockfd, (struct sockaddr *)&addr, len);
        if (ret < 0)
        {
            ERR_LOG("BIND ADDRESS FAILED!");
            return false;
        }
        return true;
    }
    // 开始监听
    bool Listen(int backlog = MAX_LISTEN)
    {
        // int listen(int backlog)
        int ret = listen(_sockfd, backlog);
        if (ret < 0)
        {
            ERR_LOG("SOCKET LISTEN FAILED!");
            return false;
        }
        return true;
    }
    // 向服务器发起连接
    bool Connect(const std::string &ip, uint16_t port)
    {
        struct sockaddr_in addr;
        addr.sin_family = AF_INET;
        addr.sin_port = htons(port);
        addr.sin_addr.s_addr = inet_addr(ip.c_str());
        socklen_t len = sizeof(struct sockaddr_in);
        // int connect(int sockfd, struct sockaddr*addr, socklen_t len);
        int ret = connect(_sockfd, (struct sockaddr *)&addr, len);
        if (ret < 0)
        {
            ERR_LOG("CONNECT SERVER FAILED!, %s", strerror(errno));
            return false;
        }
        return true;
    }
    // 获取新连接
    int Accept()
    {
        // int accept(int sockfd, struct sockaddr *addr, socklen_t *len);
        int newfd = accept(_sockfd, NULL, NULL);
        if (newfd < 0)
        {
            ERR_LOG("SOCKET ACCEPT FAILED!");
            return -1;
        }
        return newfd;
    }
    // 接收数据
    ssize_t Recv(void *buf, size_t len, int flag = 0)
    {
        // ssize_t recv(int sockfd, void *buf, size_t len, int flag);
        ssize_t ret = recv(_sockfd, buf, len, flag);
        if (ret <= 0)
        {
            // EAGAIN 当前socket的接收缓冲区中没有数据了，在非阻塞的情况下才会有这个错误
            // EINTR  表示当前socket的阻塞等待，被信号打断了，
            if (errno == EAGAIN || errno == EINTR)
            {
                return 0; // 表示这次接收没有接收到数据
            }
            ERR_LOG("SOCKET RECV FAILED!!");
            return -1;
        }
        return ret; // 实际接收的数据长度
    }
    ssize_t NonBlockRecv(void *buf, size_t len)
    {
        return Recv(buf, len, MSG_DONTWAIT); // MSG_DONTWAIT 表示当前接收为非阻塞。
    }
    // 发送数据
    ssize_t Send(const void *buf, size_t len, int flag = 0)
    {
        // ssize_t send(int sockfd, void *data, size_t len, int flag);
        ssize_t ret = send(_sockfd, buf, len, flag);
        if (ret < 0)
        {
            if (errno == EAGAIN || errno == EINTR)
            {
                return 0;
            }
            ERR_LOG("SOCKET SEND FAILED!!");
            return -1;
        }
        return ret; // 实际发送的数据长度
    }
    ssize_t NonBlockSend(void *buf, size_t len)
    {
        if (len == 0)
            return 0;
        return Send(buf, len, MSG_DONTWAIT); // MSG_DONTWAIT 表示当前发送为非阻塞。
    }
    // 关闭套接字
    void Close()
    {
        if (_sockfd != -1)
        {
            close(_sockfd);
            _sockfd = -1;
        }
    }
    // 创建一个服务端连接
    bool CreateServer(uint16_t port, const std::string &ip = "0.0.0.0", bool block_flag = false)
    {
        // 1. 创建套接字，2. 绑定地址，3. 开始监听，4. 设置非阻塞， 5. 启动地址重用
        if (Create() == false)
            return false;
        if (block_flag)
            NonBlock();
        if (Bind(ip, port) == false)
            return false;
        if (Listen() == false)
            return false;
        ReuseAddress();
        return true;
    }
    // 创建一个客户端连接
    bool CreateClient(uint16_t port, const std::string &ip)
    {
        // 1. 创建套接字，2.指向连接服务器
        if (Create() == false)
            return false;
        if (Connect(ip, port) == false)
            return false;
        return true;
    }
    // 设置套接字选项---开启地址端口重用
    void ReuseAddress()
    {
        // int setsockopt(int fd, int leve, int optname, void *val, int vallen)
        int val = 1;
        setsockopt(_sockfd, SOL_SOCKET, SO_REUSEADDR, (void *)&val, sizeof(int));
        val = 1;
        setsockopt(_sockfd, SOL_SOCKET, SO_REUSEPORT, (void *)&val, sizeof(int));
    }
    // 设置套接字阻塞属性-- 设置为非阻塞
    void NonBlock()
    {
        // int fcntl(int fd, int cmd, ... /* arg */ );
        int flag = fcntl(_sockfd, F_GETFL, 0);
        fcntl(_sockfd, F_SETFL, flag | O_NONBLOCK);
    }
};

// 我们使用epoll来对文件描述符进行等待管理
// 首先 对于每个文件描述符，要让epoll知道该fd关心什么events
// epoll在会返回已经准备好的fd的实际的就绪事件revents
// 未来，对于每个连接，都拥有自己的Channel，而Channel要做的就是管理连接的事件
// 而事件可能有多种：如监听fd需要关心读事件等，普通fd需要关心读写事件等
// Channel的设计需要综合考虑Connection和Epoll模块之间的关联
// 当新建一个channel时，需要设置其关心读事件（channel本身的接口），并把它挂到epoll的红黑树上（epoll的接口），并托付给epoll模块进行管理
// 然后进行epoll_wait，得到已经就绪的revents，并设置进channel（channel的接口）。外层的eventLoop得到已经就绪的channel，挨个去执行channel的handleEvents

// Channel的主要任务：1、设置fd关心的事件，保存已经就绪的事件。
// 2、为每种事件设置对应的处理函数（由于一个连接怎么去处理事情只有connection自己知道，所以回调函数实际由connection提供，在连接建立好时由acceptor模块设置）
//    因为读写等事件的操作对象实际是连接的缓冲区——即connection的buffer模块，所以未来的回调函数设计中要带有connection 的指针
// 3、根据不同的revents去选择执行不同的回调函数

// 还需注意一个功能：对于每条连接，我们在设置读时间之后要设置定时销毁任务，但只要该连接触发了任意事件，我们就视该连接为活跃连接，需要刷新其定时任务
// 所以我们需要另外提供一个函数，用于只要触发了任意事件的就绪，就去及时刷新该定时任务

class Poller;
class EventLoop;
class Channel
{
private:
    int _fd;
    EventLoop *_event_loop;
    uint32_t _events;  // 当前需要监控的事件
    uint32_t _revents; // 当前连接触发的事件
    using EventCallback = std::function<void()>;
    EventCallback _read_callback;  // 可读事件被触发的回调函数
    EventCallback _write_callback; // 可写事件被触发的回调函数
    EventCallback _error_callback; // 错误事件被触发的回调函数
    EventCallback _close_callback; // 连接断开事件被触发的回调函数
    EventCallback _event_callback; // 任意事件被触发的回调函数
public:
    Channel(EventLoop *event_loop, int fd) : _fd(fd), _events(0), _revents(0), _event_loop(event_loop) {}
    int Fd() { return _fd; }
    uint32_t Events() { return _events; }                   // 获取想要监控的事件
    void SetREvents(uint32_t events) { _revents = events; } // 设置实际就绪的事件
    void SetReadCallback(const EventCallback &cb) { _read_callback = cb; }
    void SetWriteCallback(const EventCallback &cb) { _write_callback = cb; }
    void SetErrorCallback(const EventCallback &cb) { _error_callback = cb; }
    void SetCloseCallback(const EventCallback &cb) { _close_callback = cb; }
    void SetEventCallback(const EventCallback &cb) { _event_callback = cb; }
    // 当前是否监控了可读
    bool ReadAble() { return (_events & EPOLLIN); }
    // 当前是否监控了可写
    bool WriteAble() { return (_events & EPOLLOUT); }
    // 启动读事件监控
    void EnableRead()
    {
        _events |= EPOLLIN;
        Update();
    }
    // 启动写事件监控
    void EnableWrite()
    {
        _events |= EPOLLOUT;
        Update();
    }
    // 关闭读事件监控
    void DisableRead()
    {
        _events &= ~EPOLLIN;
        Update();
    }
    // 关闭写事件监控
    void DisableWrite()
    {
        _events &= ~EPOLLOUT;
        Update();
    }
    // 关闭所有事件监控
    void DisableAll()
    {
        _events = 0;
        Update();
    }
    // 移除监控
    void Remove();
    void Update();
    // 事件处理，一旦连接触发了事件，就调用这个函数，自己触发了什么事件如何处理自己决定
    void HandleEvent()
    {
        if ((_revents & EPOLLIN) || (_revents & EPOLLRDHUP) || (_revents & EPOLLPRI))
        {
            /*不管任何事件，都调用的回调函数*/
            if (_read_callback)
                _read_callback();
        }
        /*有可能会释放连接的操作事件，一次只处理一个*/
        if (_revents & EPOLLOUT)
        {
            if (_write_callback)
                _write_callback();
        }
        else if (_revents & EPOLLERR)
        {
            if (_error_callback)
                _error_callback(); // 一旦出错，就会释放连接，因此要放到前边调用任意回调
        }
        else if (_revents & EPOLLHUP)
        {
            if (_close_callback)
                _close_callback();
        }
        if (_event_callback)
            _event_callback();
    }
};

#define MAX_EPOLLEVENTS 1024
class Poller
{
private:
    int _epfd;
    struct epoll_event _evs[MAX_EPOLLEVENTS];
    std::unordered_map<int, Channel *> _channels;

private:
    // 对epoll的直接操作
    void Update(Channel *channel, int op)
    {
        // int epoll_ctl(int epfd, int op,  int fd,  struct epoll_event *ev);
        int fd = channel->Fd();
        struct epoll_event ev;
        ev.data.fd = fd;
        ev.events = channel->Events();
        int ret = epoll_ctl(_epfd, op, fd, &ev);
        if (ret < 0)
        {
            ERR_LOG("EPOLLCTL FAILED!, %s",strerror(errno));
        }
        return;
    }
    // 判断一个Channel是否已经添加了事件监控
    bool HasChannel(Channel *channel)
    {
        auto it = _channels.find(channel->Fd());
        if (it == _channels.end())
        {
            return false;
        }
        return true;
    }

public:
    Poller()
    {
        _epfd = epoll_create(MAX_EPOLLEVENTS);
        if (_epfd < 0)
        {
            ERR_LOG("EPOLL CREATE FAILED!!");
            abort(); // 退出程序
        }
    }
    // 添加或修改监控事件
    void UpdateEvent(Channel *channel)
    {
        bool ret = HasChannel(channel);
        if (ret == false)
        {
            // 不存在则添加
            _channels.insert(std::make_pair(channel->Fd(), channel));
            return Update(channel, EPOLL_CTL_ADD);
        }
        return Update(channel, EPOLL_CTL_MOD);
    }
    // 移除监控
    void RemoveEvent(Channel *channel)
    {
        auto it = _channels.find(channel->Fd());
        if (it != _channels.end())
        {
            _channels.erase(it);
        }
        Update(channel, EPOLL_CTL_DEL);
    }
    // 开始监控，返回活跃连接
    void Poll(std::vector<Channel *> *active)
    {
        // int epoll_wait(int epfd, struct epoll_event *evs, int maxevents, int timeout)
        int nfds = epoll_wait(_epfd, _evs, MAX_EPOLLEVENTS, -1);
        if (nfds < 0)
        {
            if (errno == EINTR)
            {
                return;
            }
            ERR_LOG("EPOLL WAIT ERROR:%s\n", strerror(errno));
            abort(); // 退出程序
        }
        for (int i = 0; i < nfds; i++)
        {
            auto it = _channels.find(_evs[i].data.fd);
            assert(it != _channels.end());
            it->second->SetREvents(_evs[i].events); // 设置实际就绪的事件
            active->push_back(it->second);
        }
        return;
    }
};
// 定时任务类设计
class TimerTask
{
    using TimerTaskHandler_t = std::function<void(void)>;      // 定时任务回调函数
    using RemoveUpperManagement_t = std::function<void(void)>; // 移除上层对该定时任务的管理回调函数
private:
    uint64_t _timer_id;                                  // 定时任务唯一标识，与Connection类相互关联
    int _timeout;                                        // 定时时长
    bool _canceled;                                      // 定时任务是否被取消，被取消则不执行，默认设置为false
    TimerTaskHandler_t _call_back_handle_task;           // 上层提供需要执行的任务函数
    RemoveUpperManagement_t _call_back_remove_timertask; // 上层提供移除上层对定时任务的管理回调函数
public:
    TimerTask(uint64_t timer_id, int timeout)
        : _timer_id(timer_id), _timeout(timeout), _canceled(false)
    {
    }

    ~TimerTask()
    {
        // 在析构函数进行时，如果定时任务未被取消，执行定时任务；
        if (!_canceled && _call_back_handle_task)
            _call_back_handle_task();
        // 同时，由于定时任务在上层使用shared_ptr管理，该定时任务对象析构时则代表定时任务生命周期已经到达，移除上层对该任务的管理资源
        if (_call_back_remove_timertask)
            _call_back_remove_timertask();
    }

public:
    // 为外界提供一系列操作接口
    uint64_t Id() { return _timer_id; }
    void Canceled() { _canceled = true; }
    int DelayTime() { return _timeout; }
    void SetTimerTaskHandler(TimerTaskHandler_t call_back) { _call_back_handle_task = call_back; }
    void SetRemoveUpperManagement(RemoveUpperManagement_t call_back) { _call_back_remove_timertask = call_back; }
};

#define TIMERWHEELMAXCAPACITY 60
// 时间轮类设计——使用数组组织
class TimerWheel
{
    using TimerTaskHandler_t = std::function<void(void)>; // 定时任务回调函数
    using SharedPtr_t = std::shared_ptr<TimerTask>;
    using WeakPtr_t = std::weak_ptr<TimerTask>;

private:
    // 定时器相关操作
    static int CreateTimerFd()
    {
        int timer_fd = timerfd_create(CLOCK_MONOTONIC, 0);
        if (timer_fd < 0)
        {
            ERR_LOG("CreateTimerFd False!");
            abort();
        }
        struct itimerspec *old;
        struct itimerspec itime;
        itime.it_value.tv_sec = 1;
        itime.it_value.tv_nsec = 0; // 第⼀次超时时间为1s后
        itime.it_interval.tv_sec = 1;
        itime.it_interval.tv_nsec = 0; // 第⼀次超时后，每次超时的间隔时
        timerfd_settime(timer_fd, 0, &itime, NULL);
        return timer_fd;
    }

private:
    EventLoop *_event_loop;
    int _capacity;                                                 // 时间轮最大容量
    int _tick;                                                     // 滴答指针
    std::vector<std::vector<SharedPtr_t>> _timer_wheel;            // 时间轮
    std::unordered_map<uint64_t, WeakPtr_t> _timertask_management; // 管理时间轮中的所有定时任务，timer_id和weak_ptr作为键值对
    /* 为什么定时任务管理容器中使用weak_ptr，而不是使用shared_ptr呢？ */
    /* shared_ptr内部包含一个计数器，如果使用shared_ptr为shared_ptr赋值，会导致计数器+1，也就无法保证时间轮的中的定时任务在规定的时间内正确清除 */
    /* 而使用weak_ptr接收shared_ptr时不会增加shared_ptr的计数器数值，如此便既保证了对定时任务的管理，也保证了定时任务可以在对象析构的时候正确的执行 */
    int _timer_fd;                             // 定时器id
    std::unique_ptr<Channel> _timerfd_channel; // 管理timer_fd的事件
public:
    TimerWheel(EventLoop *event_loop)
        : _event_loop(event_loop), _tick(0), _capacity(TIMERWHEELMAXCAPACITY), _timer_wheel(_capacity),
          _timer_fd(CreateTimerFd()), _timerfd_channel(new Channel(_event_loop, _timer_fd))
    {
        // 当timerfd中有数据时，触发读事件就绪，设置其回调函数为处理过期任务，这一步一定在eventloop线程内
        _timerfd_channel->SetReadCallback(std::bind(&TimerWheel::HandleExpiredTasks, this));
        _timerfd_channel->EnableRead(); // 定时器读事件就绪
    }

private:
    // 一系列操作时间轮的接口

    /*定时器信息的操作有可能在多线程中进⾏，因此需要考虑线程安全问题*/
    /*如果不想加锁，那就把对定期的所有操作，都放到⼀个线程中进⾏*/
    /*所以我们将操作时间轮的相关操作绑定好参数后放入EventLoop的任务池中*/
    /*涉及到公共资源访问的方法我们要保证在同一线程中进行*/

    // 判断定时任务是否存在
    bool IsTimerTaskExist(uint64_t timer_id /*定时任务id*/)
    {
        if (_timertask_management.find(timer_id) != _timertask_management.end())
            return true;
        return false;
    }

    // 移除管理容器中的定时任务项，/*设置给Timer，最终定时任务执⾏完毕后从TimerWheel移除TimerTask信息的回调函数*/
    void RemoveTaskFromContainer(uint64_t timer_id /*定时任务id*/)
    {
        auto it = _timertask_management.find(timer_id);
        if (it == _timertask_management.end())
            return;
        _timertask_management.erase(it);
    }

    // 添加定时任务：向管理容器和时间轮中同时添加
    void AddTimerTaskHelper(TimerTaskHandler_t handle_task /*上层提供的定时任务函数*/, uint64_t timer_id /*定时任务id*/, int timeout /*定时时长*/)
    {
        // 当前时间轮最多支持60s内的定时任务
        if (timeout <= 0 || timeout > 60)
            return;
        // 当前设计仅支持一个timer_id对应一个定时任务，所以如果定时任务存在则直接返回
        if (IsTimerTaskExist(timer_id))
            return;
        // 构造定式任务类的shared_ptr
        SharedPtr_t temp(new TimerTask(timer_id, timeout));
        // 设置定时任务函数，对定时任务的管理回调函数
        temp->SetTimerTaskHandler(handle_task);
        temp->SetRemoveUpperManagement(std::bind(&TimerWheel::RemoveTaskFromContainer, this, timer_id));
        // 加入时间轮相应槽的任务队列中
        int index = (_tick + timeout) % _capacity;
        _timer_wheel[index].emplace_back(temp);
        // 托管给管理容器
        _timertask_management[timer_id] = WeakPtr_t(temp);
    }
    // 刷新定时任务
    void RefreshTimerTaskHelper(uint64_t timer_id /*定时任务id*/)
    {
        // 如果定时任务不存在，则直接返回
        if (!IsTimerTaskExist(timer_id))
            return;
        // 方式一，不会导致重复计数，因为refresh离开作用域后会自动析构，计数器自动-1
        SharedPtr_t refresh = _timertask_management[timer_id].lock();
        int timeout = refresh->DelayTime();
        // 刷新定时任务在时间轮中的位置
        _timer_wheel[(_tick + timeout) % _capacity].emplace_back(refresh);
    }
    // 取消定时任务
    void CancelTimerTaskHelper(uint64_t timer_id)
    {
        if (!IsTimerTaskExist(timer_id))
            return;
        WeakPtr_t temp = _timertask_management[timer_id];
        temp.lock()->Canceled();
    }

public:
    // 对时间轮操作接口的二次封装：压入时间轮回指的EventLoop中
    void AddTimerTask(TimerTaskHandler_t handle_task /*上层提供的定时任务函数*/, uint64_t timer_id /*定时任务id*/, int timeout /*定时时长*/);
    void RefreshTimerTask(uint64_t timer_id);
    // 取消定时任务
    void CancelTimerTask(uint64_t timer_id);

private:
    // 有可能因为其他描述符的事件处理花费事件⽐较⻓，然后在处理定时器描述符事件的时候，有可能就已经超时了很多次，获取超时次数
    uint64_t TimeOutTimes()
    {
        uint64_t times = 0;
        int ret = read(_timer_fd, &times, sizeof(times));
        if (ret < 0)
        {
            if (errno == EINTR)
            {
                return 0;
            }
            ERR_LOG("Read TimeOutTimes False!");
            abort();
        }
        return times;
    }
    /*每滴答⼀次被执⾏_tick++就会向后⾛⼀步，⾛到哪⾥，释放哪⾥的定时器，也就是执⾏哪⾥的定时任务*/
    void RunOnTimeTask()
    {
        _tick = (_tick + 1) % _capacity;
        _timer_wheel[_tick].clear();
    }

public:
    // 处理已经超时的任务，设置进入timerfd的channel的读事件关心中
    void HandleExpiredTasks()
    {
        uint64_t times = TimeOutTimes();
        for (uint64_t i = 0; i < times; i++)
        {
            RunOnTimeTask();
        }
    }
};
class EventLoop
{
    using Functor = std::function<void()>; // 任务池的任务类型
private:
    std::thread::id _thread_id;                // 一个EventLoop绑定（运行）在一个线程中，记录当前线程所绑定线程的id
    Poller _poller;                            // epoll
    std::vector<Functor> _task_pool;           // 任务池，目的是将可能产生线程安全的任务加入到EventLoop所绑定的线程中统一执行，保证线程安全
    int _event_fd;                             // eventfd用于时间通知。当向任务池中添加任务后，向_event_fd中写入数据，防止因为暂无就绪事件导致epoll_wait阻塞执行流
    std::unique_ptr<Channel> _eventfd_channel; // 为eventfd构造一个事件管理对象，当就绪时根据之前注册的回调函数执行相应的任务
    std::mutex _mutex;                         // 如果在多线程环境中，操作任务池可能引发线程安全问题。互斥锁的作用就是保证安全操作任务池
    TimerWheel _timer_wheel;                   // 时间轮
private:
    // 对eventfd的操作
    // 创建eventfd
    static int CreateEventfd()
    {
        int event_fd = eventfd(0 /*初始值*/, EFD_CLOEXEC /*防止子进程对eventfd进行复制*/ | EFD_NONBLOCK /*非阻塞读取*/);
        if (event_fd < 0)
        {
            ERR_LOG("Create Eventfd False!");
            abort();
        }
        return event_fd;
    }

    // 写入数据到eventfd
    void WeakUpEventFd()
    {
        uint64_t val = 1;
        int ret = write(_event_fd, &val, sizeof(val));
        if (ret < 0)
        {
            if (errno == EINTR)
            {
                return; // 如果是被信号打断，不影响
            }
            ERR_LOG("WeakUpEventFd False!");
            abort();
        }
    }
    // 从eventfd读取数据，注册给eventfd的Channel读事件回调
    void ReadEventfd()
    {
        uint64_t res = 0;
        int ret = read(_event_fd, &res, sizeof(res));
        if (ret < 0)
        {
            // 由于eventfd设置了NONBLOCK模式，当eventfd中无数据时，会直接返回-1，错误码设置为EAGAIN，表示下次再进行读取
            // EINTR -- 被信号打断； EAGAIN -- 表⽰⽆数据可读
            if (errno == EINTR || errno == EAGAIN)
            {
                return;
            }
            ERR_LOG("READ EVENTFD FAILED!");
            abort();
        }
        return;
    }

public:
    // 构造
    EventLoop() : _thread_id(std::this_thread::get_id()), _event_fd(CreateEventfd()), _eventfd_channel(new Channel(this, _event_fd)), _timer_wheel(this)
    {
        // 设置读回调
        _eventfd_channel->SetReadCallback(std::bind(&EventLoop::ReadEventfd, this));
    }

public:
    // 对Poller行为的封装
    // 添加或修改监控事件
    void UpdateEvent(Channel *channel)
    {
        _poller.UpdateEvent(channel);
    }
    // 移除监控
    void RemoveEvent(Channel *channel)
    {
        _poller.RemoveEvent(channel);
    }

private:
    void RunAllTask()
    {
        std::vector<Functor> temp;
        // 局部域，模拟RAII类型的互斥锁的使用
        {
            std::unique_lock<std::mutex> _lock(_mutex); // 竞争锁
            // 单执行流进入，先到先得，同时清空任务池
            _task_pool.swap(temp);
        }
        // 执行任务池中的任务
        for (auto &t : _task_pool)
        {
            t();
        }
    }

public:
    // 对任务池的操作
    // ⽤于判断当前线程是否是EventLoop对应的线程；
    bool IsInLoop()
    {
        return (_thread_id == std::this_thread::get_id());
    }
    void AssertInLoop()
    {
        assert(_thread_id == std::this_thread::get_id());
    }
    // 判断将要执⾏的任务是否处于当前线程中，如果是则执⾏，不是则压⼊队列。
    void RunInLoop(const Functor &cb)
    {
        if (IsInLoop())
        {
            return cb();
        }
        return QueueInLoop(cb);
    }
    // 将操作压⼊任务池
    void QueueInLoop(const Functor &cb)
    {
        {
            std::unique_lock<std::mutex> _lock(_mutex);
            _task_pool.push_back(cb);
        }
        // 唤醒有可能因为没有事件就绪，⽽导致的epoll阻塞；
        // 其实就是给eventfd写⼊⼀个数据，eventfd就会触发可读事件
        WeakUpEventFd();
    }

public:
    // 一个EventLoop实际上就是一个Reactor模式，创建Reactor的行为，即进行事件派发
    void Start()
    {
        while (true)
        {
            // 1、处理epoll中就绪的事件
            std::vector<Channel *> active;
            _poller.Poll(&active);
            // 处理active中的事件
            for (auto &ev : active)
            {
                ev->HandleEvent();
            }
            // 2、处理任务池中的任务
            RunAllTask();
        }
    }

    // 对时间轮的操作
    void AddTimerTask(Functor handle_task /*上层提供的定时任务函数*/, uint64_t timer_id /*定时任务id*/, int timeout /*定时时长*/)
    {
        _timer_wheel.AddTimerTask(handle_task, timer_id, timeout);
    }

    void RefreshTimerTask(uint64_t timer_id)
    {
        _timer_wheel.RefreshTimerTask(timer_id);
    }
    // 取消定时任务
    void CancelTimerTask(uint64_t timer_id)
    {
        _timer_wheel.CancelTimerTask(timer_id);
    }
};

// 及时更新状态
void Channel::Update()
{
    _event_loop->UpdateEvent(this);
}
// 在连接关闭时移除事件关心
void Channel::Remove()
{
    _event_loop->RemoveEvent(this);
}

// 对时间轮操作接口的二次封装：压入时间轮回指的EventLoop中
void TimerWheel::AddTimerTask(TimerTaskHandler_t handle_task /*上层提供的定时任务函数*/, uint64_t timer_id /*定时任务id*/, int timeout /*定时时长*/)
{
    _event_loop->RunInLoop(std::bind(&TimerWheel::AddTimerTaskHelper, this, handle_task, timer_id, timeout));
}
void TimerWheel::RefreshTimerTask(uint64_t timer_id)
{
    _event_loop->RunInLoop(std::bind(&TimerWheel::RefreshTimerTaskHelper, this, timer_id));
}
// 取消定时任务
void TimerWheel::CancelTimerTask(uint64_t timer_id)
{
    _event_loop->RunInLoop(std::bind(&TimerWheel::CancelTimerTaskHelper, this, timer_id));
}

#endif